import { RegisterComponent } from "@feng3d/ecs";
import { PerspectiveCamera, Vector4 } from "../../thirdparty/three/imports";
import { Node3D } from "../core/Node3D";
import { Camera3D } from "./Camera3D";

declare module "@feng3d/ecs"
{
    interface ComponentMap { PerspectiveCamera3D: PerspectiveCamera3D; }
}

export interface PerspectiveCamera3D
{
    /**
     * @private
     */
    get _camera(): PerspectiveCamera;
    set _camera(v);
}

/**
 * 3D透视摄像机，包装`three`中`PerspectiveCamera`。
 */
@RegisterComponent({ name: 'PerspectiveCamera3D' })
export class PerspectiveCamera3D extends Camera3D
{
    get fov()
    {
        if (this._camera)
        {
            this._fov = this._camera.fov;
        }

        return this._fov;
    }
    set fov(v)
    {
        this._fov = v;
        if (this._camera)
        {
            this._camera.fov = this._fov;
        }
    }
    private _fov: number;

    get aspect()
    {
        if (this._camera)
        {
            this._aspect = this._camera.aspect;
        }

        return this._aspect;
    }
    set aspect(v)
    {
        this._aspect = v;
        if (this._camera)
        {
            this._camera.aspect = this._aspect;
        }
    }
    private _aspect: number;

    get near()
    {
        if (this._camera)
        {
            this._near = this._camera.near;
        }

        return this._near;
    }
    set near(v)
    {
        this._near = v;
        if (this._camera)
        {
            this._camera.near = this._near;
        }
    }
    private _near: number;

    get far()
    {
        if (this._camera)
        {
            this._far = this._camera.far;
        }

        return this._far;
    }
    set far(v)
    {
        this._far = v;
        if (this._camera)
        {
            this._camera.far = this._far;
        }
    }
    private _far: number;

    get focalLength()
    {
        if (this._camera)
        {
            this._focalLength = this._camera["focalLength"];
        }

        return this._focalLength;
    }
    set focalLength(v)
    {
        this._focalLength = v;
        if (this._camera)
        {
            this._camera["focalLength"] = this._focalLength;
        }
    }
    private _focalLength: number;

    get viewport(): Vector4
    {
        return this._camera["viewport"];
    }
    set viewport(v)
    {
        this._camera["viewport"] = v;
    }

    init()
    {
        this._camera = this._camera || new PerspectiveCamera(this.fov, this.aspect, this.near, this.far);
        this._entity.isPerspectiveCamera = true;

        super.init();
    }

    destroy(): void
    {
        super.destroy();

        this._entity.isPerspectiveCamera = false;
    }

    updateProjectionMatrix()
    {
        this._camera.updateProjectionMatrix();
    }

    setViewOffset(fullWidth: number, fullHeight: number, x: number, y: number, width: number, height: number)
    {
        this._camera.setViewOffset(fullWidth, fullHeight, x, y, width, height);
    }

    _setCamera(camera: PerspectiveCamera)
    {
        this._entity._group.remove(this._camera);
        this._camera = camera;
        this._entity._group.add(this._camera);
    }

    static get(camera: PerspectiveCamera)
    {
        const camera3D = new Node3D().addComponent("PerspectiveCamera3D");

        camera3D._setCamera(camera);

        return camera3D;
    }
}
